package com.yida.gwj.basis.controller.common;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.PhoneUtil;
import com.yida.common.core.constant.CacheConstants;
import com.yida.common.core.constant.SecurityConstants;
import com.yida.common.core.domain.R;
import com.yida.common.core.exception.ServiceException;
import com.yida.common.core.utils.CheckRemoteServiceResultUtils;
import com.yida.common.core.utils.StringUtils;
import com.yida.common.core.utils.file.FileTypeUtils;
import com.yida.common.core.utils.file.MimeTypeUtils;
import com.yida.common.core.web.controller.BaseController;
import com.yida.common.core.web.domain.AjaxResult;
import com.yida.common.log.annotation.Log;
import com.yida.common.log.enums.BusinessType;
import com.yida.common.redis.service.RedisService;
import com.yida.gwj.basis.domain.request.GwjOwnerAttestRequest;
import com.yida.gwj.basis.service.IGwjOwnerAttestService;
import com.yida.gwj.common.domain.*;
import com.yida.gwj.common.domain.dto.GwjBaseBuildSelectDTO;
import com.yida.gwj.common.domain.dto.GwjBaseCommunitySelectDTO;
import com.yida.gwj.common.domain.dto.GwjBaseHouseSelectDTO;
import com.yida.gwj.common.domain.dto.GwjBaseOwnerHouseListDTO;
import com.yida.gwj.common.domain.request.GwjOwnerLoginRequest;
import com.yida.gwj.common.service.IGwjBaseBuildService;
import com.yida.gwj.common.service.IGwjBaseCommunityService;
import com.yida.gwj.common.service.IGwjBaseHouseService;
import com.yida.gwj.common.service.IGwjBaseOwnerService;
import com.yida.system.api.RemoteFileService;
import com.yida.system.api.RemoteSmsService;
import com.yida.system.api.domain.SysFile;
import com.yida.system.api.domain.SysSms;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 基础数据查询模块
 *
 * @author hmh
 * @date 2022-11-15
 */
@RestController
@RequestMapping("/public")
@Api(tags = "对外开放的接口")
public class GwjPublicController extends BaseController {

    @Resource
    private IGwjBaseOwnerService gwjBaseOwnerService;

    @Resource
    private IGwjBaseCommunityService communityService;

    @Resource
    private IGwjBaseHouseService houseService;

    @Resource
    private IGwjBaseBuildService buildService;

    @Resource
    private RedisService redisService;

    @Resource
    private RemoteSmsService remoteSmsService;

    @Resource
    private RemoteFileService remoteFileService;

    @Resource
    private IGwjOwnerAttestService gwjOwnerAttestService;

    private final String GWJ_OWNER_ATTEST_SMS_KEY = "gwj_owner_attest";

    private final String GWJ_SELECT_SMS_KEY = "gwj_select";

    /**
     * 根据小区ID查询小区信息 lqq
     *
     * @param areaId 小区ID
     * @return /
     */
    @ApiOperation(value = "根据地区ID查询小区信息列表", response = GwjBaseCommunitySelectDTO.class)
    @GetMapping("/communitySelect/{areaId}")
    public AjaxResult communitySelect(@PathVariable Long areaId) {
        List<GwjBaseCommunity> communities = communityService.selectCommunityList(new GwjBaseCommunity() {{
            setAreaId(areaId);
        }});
        if (StringUtils.isNotEmpty(communities)) {
            return AjaxResult.success(BeanUtil.copyToList(communities, GwjBaseCommunitySelectDTO.class));
        }
        return AjaxResult.success();
    }

    /**
     * 查询基础楼栋列表(选择楼栋) lqq
     *
     * @param communityId 请求参数
     * @return /
     */
    @ApiOperation(value = "根据小区ID查询基础楼栋列表", response = GwjBaseBuildSelectDTO.class)
    @GetMapping("/buildSelect/{communityId}")
    public AjaxResult buildInfo(@PathVariable Long communityId) {
        List<GwjBaseBuild> builds = buildService.selectGwjBaseBuildListByCommunityId(communityId);
        if (StringUtils.isNotEmpty(builds)) {
            return AjaxResult.success(BeanUtil.copyToList(builds, GwjBaseBuildSelectDTO.class));
        }
        return AjaxResult.success();
    }

    /**
     * 根据小区ID查询房屋信息 lqq
     *
     * @param areaId 小区ID
     * @return /
     */
    @ApiOperation(value = "根据地区ID和楼栋标识码查询房屋信息列表", response = GwjBaseHouseSelectDTO.class)
    @GetMapping("/houseSelect/{areaId}/{buildCode}")
    public AjaxResult houseSelect(@PathVariable("areaId") Long areaId, @PathVariable("buildCode") String buildCode) {
        List<GwjBaseHouse> houses = houseService.selectGwjBaseHouseList(new GwjBaseHouse() {{
            setAreaId(areaId);
            setBuildCode(buildCode);
        }});
        if (StringUtils.isNotEmpty(houses)) {
            return AjaxResult.success(BeanUtil.copyToList(houses, GwjBaseHouseSelectDTO.class));
        }
        return AjaxResult.success();
    }

    /**
     * 业主信息认证-提交认证资料
     *
     * @param request 请求参数
     * @return /
     */
    @ApiOperation(value = "业主信息认证-提交认证资料")
    @PostMapping("/ownerAttest/submit")
    @Log(title = "业主信息认证-提交", businessType = BusinessType.INSERT, systemName = "gwj")
    public AjaxResult submit(@Validated @RequestBody GwjOwnerAttestRequest request) {
        //验证短信
        String smsCode = redisService.getCacheObject(getSmsCacheKey(request.getOwnerPhone(),GWJ_OWNER_ATTEST_SMS_KEY));
        if (StringUtils.isBlank(smsCode)) {
            throw new ServiceException("验证码不存在，请重新获取");
        }
        if (!request.getSmsCode().equals(smsCode)) {
            throw new ServiceException("验证码错误");
        }
        //校验手机格式
        if (!PhoneUtil.isPhone(request.getOwnerPhone())) {
            throw new ServiceException("提交失败,手机号码格式有误");
        }
        //校验身份证格式
        if (!IdcardUtil.isValidCard(request.getCardNum())) {
            throw new ServiceException("提交失败,身份证号码格式有误");
        }
        return toAjax(gwjOwnerAttestService.submit(request));
    }

    /**
     * 业主信息认证-房产证上传
     *
     * @param file 房产证图片
     * @return /
     */
    @Log(title = "业主信息认证-房产证上传", businessType = BusinessType.UPDATE, systemName = "gwj")
    @PostMapping(value = "/ownerAttest/upload", headers = "content-type=multipart/form-data")
    @ApiOperation(value = "业主信息认证-房产证上传", response = GwjUploadFile.class)
    public AjaxResult uploadFile(@RequestPart("file") MultipartFile file) {
        if (file == null || file.isEmpty()) {
            return AjaxResult.error("上传房产证失败,图片异常");
        }
        String extension = FileTypeUtils.getExtension(file);
        if (!StringUtils.equalsAnyIgnoreCase(extension, MimeTypeUtils.IMAGE_EXTENSION)) {
            return AjaxResult.error("上传房产证失败,图片格式不正确" + Arrays.toString(MimeTypeUtils.IMAGE_EXTENSION) + "格式");
        }
        R<SysFile> fileResult = remoteFileService.upload(file);
        if (StringUtils.isNull(fileResult) || StringUtils.isNull(fileResult.getData())) {
            return AjaxResult.error("上传房产证失败,图片服务异常");
        }
        return AjaxResult.success("上传房产证成功", fileResult.getData().getUrl());
    }

    /**
     * 业主信息认证-发送短信
     *
     * @param phoneNum 手机号码
     * @return /
     */
    @ApiOperation(value = "业主信息认证-发送短信")
    @PostMapping("/ownerAttest/sendSms/{phoneNum}")
    public AjaxResult sendSms(@PathVariable String phoneNum) {
        if (!PhoneUtil.isPhone(phoneNum)) {
            return AjaxResult.error("发送失败,手机号码格式有误");
        }
        //发送短信
        R<SysSms> r = remoteSmsService.sendSmsByPhonenumber(new SysSms() {{
            setSmsType(1);
            setPhonenumber(phoneNum);
            setSms("短信");
            setSmsSource(GWJ_OWNER_ATTEST_SMS_KEY);
        }}, SecurityConstants.INNER);
        AjaxResult result = toAjax(!CheckRemoteServiceResultUtils.isCodeFail(r));
        if (StringUtils.isNotNull(r.getData())) {
            result.put(AjaxResult.MSG_TAG, r.getData().getSms());
        } else {
            result.put(AjaxResult.MSG_TAG, r.getMsg());
        }
        return result;
    }

    /**
     * 公维金查询-房屋信息列表
     *
     * @param request 请求参数
     * @return /
     */
    @ApiOperation(value = "公维金查询-房屋信息列表", response = GwjBaseOwnerHouseListDTO.class)
    @PostMapping("/gwjSelect/houseList")
    public AjaxResult select(@Validated @RequestBody GwjOwnerLoginRequest request) {
        // 用户名或密码为空 错误
        if (StringUtils.isAnyBlank(request.getCardNum(), request.getOwnerPhone(), request.getOwnerName())) {
            throw new ServiceException("查询失败,姓名/身份证号码/手机号码必须填写");
        }
        //校验手机格式
        if (!PhoneUtil.isPhone(request.getOwnerPhone())) {
            throw new ServiceException("查询失败,手机号码格式有误");
        }
        //校验身份证格式
        if (!IdcardUtil.isValidCard(request.getCardNum())) {
            throw new ServiceException("查询失败,身份证号码格式有误");
        }
        //验证短信
        String smsCode = redisService.getCacheObject(getSmsCacheKey(request.getOwnerPhone(),GWJ_SELECT_SMS_KEY));
        if (StringUtils.isBlank(smsCode)) {
            throw new ServiceException("验证码不存在，请重新获取");
        }
        if (!request.getSmsCode().equals(smsCode)) {
            throw new ServiceException("验证码错误");
        }
        //根据手机号码查询用户集合
        List<GwjBaseOwnerHouseListDTO> owners = gwjBaseOwnerService.selectGwjOwnerHouseList(new GwjBaseOwner() {{
            setOwnerName(request.getOwnerName());
            setCardNum(request.getCardNum());
        }});
        if (StringUtils.isEmpty(owners)) {
            owners = new ArrayList<>();
        }
        //隐藏身份证号码
        owners.forEach(o -> o.setCardNum(""));
        return AjaxResult.success(owners);
    }

    /**
     * 公维金查询-发送短信
     *
     * @param phoneNum 手机号码
     * @return /
     */
    @ApiOperation(value = "公维金查询-发送短信")
    @PostMapping("/gwjSelect/sendSms/{phoneNum}")
    public AjaxResult gwjSendSms(@PathVariable String phoneNum) {
        if (!PhoneUtil.isPhone(phoneNum)) {
            return AjaxResult.error("发送失败,手机号码格式有误");
        }
        //发送短信
        R<SysSms> r = remoteSmsService.sendSmsByPhonenumber(new SysSms() {{
            setSmsType(1);
            setPhonenumber(phoneNum);
            setSms("短信");
            setSmsSource(GWJ_SELECT_SMS_KEY);
        }}, SecurityConstants.INNER);
        AjaxResult result = toAjax(!CheckRemoteServiceResultUtils.isCodeFail(r));
        if (StringUtils.isNotNull(r.getData())) {
            result.put(AjaxResult.MSG_TAG, r.getData().getSms());
        } else {
            result.put(AjaxResult.MSG_TAG, r.getMsg());
        }
        return result;
    }

    /**
     * 拼接缓存key
     *
     * @param ownerPhone 电话
     * @param key        前缀
     * @return /
     */
    public String getSmsCacheKey(String ownerPhone, String key) {
        return CacheConstants.SMS_CODE_EXPIRATION_KEY + key + ":" + ownerPhone;
    }
}
